<template>
  <div class="pdf-container">
    <!-- PDF预览区域 -->
    <div v-if="showPreview" class="preview-wrapper">
      <div class="preview-content">
        <!-- 左侧缩略图栏 -->
        <div class="thumbnail-sidebar">
          <div class="thumbnail-list" ref="thumbnailList" @scroll="handleThumbnailScroll">
            <div
                v-for="(page, index) in pages"
                :key="`page-${page.index}-${page.version || 0}`"
                class="thumbnail-item"
                :class="{ active: currentPage === index + 1, 'processing': page.status === 'processing', 'error': page.status === 'error' }"
                @click="goToPage(index + 1)"
            >
              <div class="thumbnail-wrapper">
                <!-- 处理中状态 -->
                <div v-if="page.status === 'processing'" class="processing-placeholder">
                  <div class="processing-content">
                    <div class="processing-spinner"></div>
                    <div class="processing-text">处理中...</div>
                  </div>
                </div>
                <!-- 错误状态 -->
                <div v-else-if="page.status === 'error'" class="error-placeholder">
                  <div class="error-content">
                    <div class="error-icon">⚠️</div>
                    <div class="error-text">加载失败</div>
                    <button class="retry-btn" @click.stop="retryLoadPage(index)">重试</button>
                  </div>
                </div>
                <!-- 正常图片 -->
                <img
                    v-else-if="page.status === 'loaded' && shouldLoadThumbnail(index)"
                    :src="getThumbnailUrl(page, index)"
                    class="thumbnail-image"
                    alt="Page thumbnail"
                    @error="handleImageError($event, index)"
                    @load="handleThumbnailLoad(index)"
                    loading="lazy"
                />
                <!-- 懒加载占位符 -->
                <div v-else class="lazy-placeholder">
                  <div class="lazy-content">
                    <div class="lazy-icon">📄</div>
                    <div class="lazy-text">第{{ index + 1 }}页</div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
        <!-- 右侧主预览区域 -->
        <div class="preview-main">
          <!-- 工具栏 -->
          <div class="toolbar">
            <div class="toolbar-left">
              <button @click="prevPage" :disabled="currentPage <= 1" class="btn-tool">
                &lt;
              </button>
              <span class="page-info">
                第 {{ currentPage }} 页 / 共 {{ totalPages }} 页
                <span v-if="processingPages > 0" class="processing-info"> ({{ processingPages }} 页处理中) </span>
              </span>
              <button @click="nextPage" :disabled="currentPage >= totalPages" class="btn-tool">
                &gt;
              </button>
            </div>
            <div class="toolbar-right">
              <button @click="zoomOut" class="btn-tool"> - </button>
              <span class="zoom-info">{{ Math.round(scale * 100) }}%</span>
              <button @click="zoomIn" class="btn-tool"> + </button>
              <button @click="downloadCurrentPage" class="btn-tool" title="下载当前页"> 下载 </button>
            </div>
          </div>
          <!-- 主预览区域 -->
          <div class="canvas-container" ref="canvasContainer">
            <div class="image-wrapper" :style="imageStyle">
              <!-- 当前页面处理中 -->
              <div v-if="currentPageStatus === 'processing'" class="main-processing-placeholder">
                <div class="main-processing-content">
                  <div class="main-processing-spinner"></div>
                  <p>第 {{ currentPage }} 页正在处理中...</p>
                </div>
              </div>
              <!-- 当前页面加载失败 -->
              <div v-else-if="currentPageStatus === 'error'" class="main-error-placeholder">
                <div class="main-error-content">
                  <div class="main-error-icon">⚠️</div>
                  <p>第 {{ currentPage }} 页加载失败</p>
                  <button class="main-retry-btn" @click="retryLoadPage(currentPage - 1)">重试</button>
                </div>
              </div>
              <!-- 正常显示图片 -->
              <img
                  v-else-if="currentPageUrl && currentPageStatus === 'loaded'"
                  :src="getMainImageUrl()"
                  class="pdf-image"
                  alt="PDF page"
                  @load="handleImageLoad"
                  @error="handleMainImageError"
                  loading="lazy"
              />
              <!-- 默认占位符 -->
              <div v-else class="no-image-placeholder">
                <div class="placeholder-content">
                  <i class="placeholder-icon">📄</i>
                  <p>页面加载中...</p>
                </div>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
    <!-- 加载动画 -->
    <div v-if="loading" class="loading-overlay">
      <div class="loading-spinner">
        <div class="spinner"></div>
        <div class="spinner-text">{{ loadingText }}</div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, reactive, watch, onMounted, nextTick, onBeforeUnmount, computed } from 'vue'
import { getPdfImageUrls } from "@/api/result/File" // 确保这个路径是正确的

// Constants
const THUMBNAIL_BUFFER = 1// 缩略图懒加载缓冲区大小

// Reactive state variables
const scale = ref(0.7)
const currentPage = ref(1)
const totalPages = ref(0)
const thumbnailList = ref(null)

// File information (simplified, just the path)
const currentFilePath = ref('')

// Lazy loading related
const visibleThumbnailRange = ref({ start: 0, end: 5 })

// Simple URL cache (no LRU, just for unique URLs)
const urlCache = new Map()

const props = defineProps({
  pdfUrl: {
    type: String,
    default: ''
  }
})

const pages = ref([])
const loadingText = ref('')
const showPreview = ref(false)
const loading = ref(false)

// Computed properties
const processingPages = computed(() => {
  return pages.value.filter(page => page.status === 'processing').length
})

const currentPageUrl = computed(() => {
  if (pages.value.length === 0 || currentPage.value <= 0 || currentPage.value > pages.value.length) {
    return null
  }
  return pages.value[currentPage.value - 1]?.url
})

const currentPageStatus = computed(() => {
  if (pages.value.length === 0 || currentPage.value <= 0 || currentPage.value > pages.value.length) {
    return 'loading'
  }
  return pages.value[currentPage.value - 1]?.status || 'loading'
})

const imageStyle = computed(() => {
  // Simplified: no rotation in this version
  return { transform: `scale(${scale.value})`, transformOrigin: 'center center' }
})

// Generate a URL with a no-cache parameter
const generateNoCacheUrl = (url) => {
  if (!url) return url;
  // 检查URL是否已经包含重复的https://，如果包含，尝试修复
  let cleanedUrl = url.replace('https://790web-thesis.https://', 'https://790web-thesis.');
  if (urlCache.has(cleanedUrl)) {
    return urlCache.get(cleanedUrl);
  }
  const randomParam = Math.random().toString(36).substring(2, 15);
  const timestamp = Date.now();
  const separator = cleanedUrl.includes('?') ? '&' : '?';
  const noCacheUrl = `${cleanedUrl}${separator}nocache=${timestamp}&rand=${randomParam}`;
  urlCache.set(cleanedUrl, noCacheUrl);
  return noCacheUrl;
};

const getThumbnailUrl = (page, index) => {
  // For thumbnails, we might want a smaller version or just the same URL
  // In this simplified version, it's the same URL with no-cache param
  return generateNoCacheUrl(page.url);
};

const getMainImageUrl = () => {
  return generateNoCacheUrl(currentPageUrl.value);
};

// Load PDF images from backend
const loadPdfImages = async (filePath) => {
  console.log('开始加载PDF图片，路径:', filePath);
  loading.value = true;
  loadingText.value = '正在加载PDF图片...';

  // Reset preview state
  showPreview.value = false;
  currentPage.value = 1;
  totalPages.value = 0;
  pages.value = [];
  currentFilePath.value = filePath;

  const encodedFilePath = encodeURIComponent(filePath);

  try {

    const response = await getPdfImageUrls(encodedFilePath);

    // **关键检查点：确保 response 和 response.data 存在**
    if (!response || !response.data) {
      throw new Error('API响应为空或数据部分缺失。请检查网络或后端返回。');
    }

    // 检查API返回数据格式是否正确，特别是 code 和 data 内部结构
    // 如果后端有提供错误信息，则使用它，否则使用通用错误信息
    if (response.code !== 200) {
      throw new Error(response.msg || 'API返回数据格式不正确或缺少必要字段。');
    }

    const { imageUrls, pageCount } = response.data;
    totalPages.value = pageCount;
    pages.value = imageUrls.map((url, index) => ({
      url: url,
      index: index + 1,
      status: index === 0 ? 'loaded' : 'pending',
      version: 0
    }));

    await nextTick();
    showPreview.value = true;
    await loadPriorityPages();
    console.log('PDF图片加载完成');
  } catch (error) {
    console.error('加载PDF图片时发生错误:', error);
    console.log('Caught error object details:', error); // <-- 关键调试信息

    let errorMessage = '未知错误';

    // 优先检查是否是后端 Result 对象被作为错误抛出
    if (typeof error === 'object' && error !== null) {
      if (error.code !== undefined && error.msg !== undefined) { // 看起来像 Result 对象
        errorMessage = error.msg || `后端返回错误码: ${error.code}`;
      } else if (error instanceof Error) { // 标准 JavaScript Error
        errorMessage = error.message;
      } else if (error.response && error.response.data && error.response.data.msg) { // Axios 错误，包含后端 msg
        errorMessage = error.response.data.msg;
      } else if (error.response && error.response.status) { // Axios 错误，包含 HTTP 状态码
        errorMessage = `HTTP 错误: ${error.response.status}`;
      } else if (typeof error.message === 'string' && error.message.length > 0) { // 带有 message 属性的普通对象
        errorMessage = error.message;
      } else {
        // 最后的尝试：将整个错误对象转换为字符串
        try {
          errorMessage = JSON.stringify(error);
        } catch (e) {
          errorMessage = '无法解析的错误对象';
        }
      }
    } else if (typeof error === 'string') { // 纯字符串错误
      errorMessage = error;
    }

    loadingText.value = `加载失败: ${errorMessage}`;
  } finally {
    loading.value = false;
  }
};

// Load current and adjacent pages first
const loadPriorityPages = async () => {
  const currentIndex = currentPage.value - 1;
  if (pages.value[currentIndex] && pages.value[currentIndex].status === 'pending') {
    await loadPageImage(currentIndex);
  }
  const priorityIndexes = [
    currentIndex - 1,
    currentIndex + 1,
  ].filter(index => index >= 0 && index < pages.value.length);
  for (const index of priorityIndexes) {
    if (pages.value[index] && pages.value[index].status === 'pending') {
      await loadPageImage(index);
      await new Promise(resolve => setTimeout(resolve, 100)); // Small delay to prevent overwhelming
    }
  }
};

// Determine if thumbnail should be loaded (for lazy loading)
const shouldLoadThumbnail = (index) => {
  const inVisibleRange = index >= visibleThumbnailRange.value.start && index <= visibleThumbnailRange.value.end;
  const isCurrentPage = index === currentPage.value - 1;
  const isAdjacentPage = Math.abs(index - (currentPage.value - 1)) <= 1;
  return inVisibleRange || isCurrentPage || isAdjacentPage;
};

// Handle thumbnail scroll for lazy loading
const handleThumbnailScroll = () => {
  if (!thumbnailList.value) return;
  const container = thumbnailList.value;
  const itemHeight = 140; // Approximate thumbnail item height from CSS
  const containerHeight = container.clientHeight;
  const scrollTop = container.scrollTop;
  const start = Math.max(0, Math.floor(scrollTop / itemHeight) - THUMBNAIL_BUFFER);
  const end = Math.min(pages.value.length - 1, Math.floor((scrollTop + containerHeight) / itemHeight) + THUMBNAIL_BUFFER);
  visibleThumbnailRange.value = { start, end };
  // Trigger loading for visible thumbnails
  for (let i = start; i <= end; i++) {
    if (pages.value[i] && pages.value[i].status === 'pending') {
      loadPageImage(i);
    }
  }
};


const loadPageImage = async (index) => {
  if (!pages.value[index] || pages.value[index].status !== 'pending') {
    return;
  }
  pages.value[index].status = 'loading';
  try {
    pages.value[index].status = 'loaded';
  } catch (error) {
    console.error(`页面 ${index + 1} 加载失败:`, error);
    pages.value[index].status = 'error';
  }
};

// Retry loading a page
const retryLoadPage = async (index) => {
  if (pages.value[index]) {
    pages.value[index].status = 'pending';
    await loadPageImage(index);
  }
};

// Page navigation functions
const goToPage = (pageNumber) => {
  if (pageNumber >= 1 && pageNumber <= totalPages.value) {
    currentPage.value = pageNumber;
    // Trigger loading for the new current page and its neighbors
    const pageIndex = pageNumber - 1;
    if (pages.value[pageIndex] && pages.value[pageIndex].status === 'pending') {
      loadPageImage(pageIndex);
    }
    const adjacentIndexes = [pageIndex - 1, pageIndex + 1];
    adjacentIndexes.forEach(index => {
      if (index >= 0 && index < pages.value.length && pages.value[index] && pages.value[index].status === 'pending') {
        loadPageImage(index);
      }
    });
  }
};

const nextPage = () => {
  if (currentPage.value < totalPages.value) {
    goToPage(currentPage.value + 1);
  }
};

const prevPage = () => {
  if (currentPage.value > 1) {
    goToPage(currentPage.value - 1);
  }
};

// Zoom functions
const zoomIn = () => {
  scale.value = Math.min(scale.value + 0.1, 3.0); // Max zoom 300%
};

const zoomOut = () => {
  scale.value = Math.max(scale.value - 0.1, 0.2); // Min zoom 20%
};

// Image load/error handlers
const handleImageLoad = () => {
  console.log('主图片加载成功');
};

const handleThumbnailLoad = (index) => {
  console.log(`缩略图 ${index + 1} 加载成功`);
  if (pages.value[index]) {
    pages.value[index].status = 'loaded';
  }
};

const handleMainImageError = (event) => {
  console.error('主图片加载失败:', event.target.src);
  if (event.target.dataset.errorHandled) {
    return;
  }
  event.target.dataset.errorHandled = 'true';
  const pageIndex = currentPage.value - 1;
  if (pages.value[pageIndex]) {
    pages.value[pageIndex].status = 'error';
  }
  alert(`第 ${currentPage.value} 页图片加载失败，请检查URL格式或网络。`); // Using alert for simplicity
  event.target.style.display = 'none'; // Hide broken image
};

const handleImageError = (event, index) => {
  console.error(`缩略图 ${index + 1} 加载失败:`, event.target.src);
  if (event.target.dataset.errorHandled) {
    return;
  }
  event.target.dataset.errorHandled = 'true';
  if (pages.value[index]) {
    pages.value[index].status = 'error';
  }
  event.target.style.display = 'none'; // Hide broken image
};

// Download current page
const downloadCurrentPage = () => {
  if (currentPageUrl.value) {
    const link = document.createElement('a');
    link.href = generateNoCacheUrl(currentPageUrl.value);
    link.download = `page-${currentPage.value}.jpg`; // Suggest a filename
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    console.log(`第 ${currentPage.value} 页下载成功`);
  }
};

// Reset preview state
const resetPreview = () => {
  showPreview.value = false;
  currentPage.value = 1;
  totalPages.value = 0;
  pages.value = [];
  urlCache.clear(); // Clear the simple URL cache
};

// Watchers and Lifecycle Hooks
watch(
    () => props.pdfUrl,
    async (newUrl) => {
      if (newUrl) {
        await nextTick(); // Ensure DOM is mounted
        await loadPdfImages(newUrl); // Load document based on new URL
      } else {
        resetPreview(); // If URL is cleared, reset preview
      }
    },
    { immediate: true } // Trigger on initial component mount
);

onMounted(async () => {
  console.log('组件挂载，props.pdfUrl:', props.pdfUrl);
  // Initial load is handled by the watcher with immediate: true
});

onBeforeUnmount(() => {
  // Clean up resources
  urlCache.clear();
  pages.value = [];
  console.log('组件已卸载，资源已清理');
});
</script>

<style scoped>
.btn-tool {
  padding: 0.5rem;
  border: none;
  background: transparent;
  border-radius: 4px;
  cursor: pointer;
  color: #4b5563;
  transition: background-color 0.2s;
  font-size: 14px;
}
.btn-tool:hover {
  background: #f3f4f6;
}
.btn-tool:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
.header h2 {
  margin: 0;
  font-size: 24px;
  font-weight: bold;
}
.thumbnail-sidebar {
  width: 160px;
  min-width: 160px;
  border-right: 1px solid #e5e7eb;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  height: 1400px; /* Adjusted height for better preview */
  overflow: hidden;
}
.thumbnail-list {
  flex: 1;
  overflow-y: auto;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0;
}
.thumbnail-item {
  position: relative;
  cursor: pointer; /* Changed from 'move' as drag-reorder is removed */
  border: 2px solid transparent;
  border-radius: 4px;
  transition: all 0.2s;
  margin: 0;
  padding: 0;
  user-select: none;
}
.thumbnail-item.active {
  border-color: #409EFF;
}
.thumbnail-item.processing {
  border-color: #f39c12;
}
.thumbnail-item.error {
  border-color: #e74c3c;
}
.thumbnail-wrapper {
  position: relative;
  overflow: hidden;
  min-height: 120px;
}
.thumbnail-image {
  width: 100%;
  height: auto;
  border-radius: 4px;
  display: block;
  min-height: 120px;
  background-color: #f5f5f5;
  transition: transform 0.3s ease;
}
/* Processing state styles */
.processing-placeholder {
  width: 100%;
  height: 120px;
  background: #fff3cd;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
  border: 1px solid #f39c12;
}
.processing-content {
  text-align: center;
  color: #856404;
}
.processing-spinner {
  width: 20px;
  height: 20px;
  border: 2px solid #f39c12;
  border-top: 2px solid transparent;
  border-radius: 50%;
  animation: spin 1s linear infinite;
  margin: 0 auto 8px;
}
.processing-text {
  font-size: 12px;
}
/* Error state styles */
.error-placeholder {
  width: 100%;
  height: 120px;
  background: #f8d7da;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
  border: 1px solid #e74c3c;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}
.error-content {
  text-align: center;
  color: #721c24;
}
.error-icon {
  font-size: 24px;
  margin-bottom: 4px;
}
.error-text {
  font-size: 12px;
  margin-bottom: 8px;
}
.retry-btn {
  padding: 2px 8px;
  background: #e74c3c;
  color: white;
  border: none;
  border-radius: 3px;
  font-size: 10px;
  cursor: pointer;
}
.retry-btn:hover {
  background: #c0392b;
}
/* Lazy loading placeholder styles */
.lazy-placeholder {
  width: 100%;
  height: 120px;
  background: #f8f9fa;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
  border: 1px dashed #dee2e6;
}
.lazy-content {
  text-align: center;
  color: #6c757d;
}
.lazy-icon {
  font-size: 24px;
  margin-bottom: 4px;
}
.lazy-text {
  font-size: 12px;
}
/* Main preview area state styles */
.main-processing-placeholder {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100%;
  width: 100%;
  background-color: #fff3cd;
  border: 2px dashed #f39c12;
  border-radius: 8px;
}
.main-processing-content {
  text-align: center;
  color: #856404;
}
.main-processing-spinner {
  width: 40px;
  height: 40px;
  border: 4px solid #f39c12;
  border-top: 4px solid transparent;
  border-radius: 50%;
  animation: spin 1s linear infinite;
  margin: 0 auto 16px;
}
.main-error-placeholder {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100%;
  width: 100%;
  background-color: #f8d7da;
  border: 2px dashed #e74c3c;
  border-radius: 8px;
}
.main-error-content {
  text-align: center;
  color: #721c24;
}
.main-error-icon {
  font-size: 48px;
  margin-bottom: 16px;
}
.main-retry-btn {
  padding: 8px 16px;
  background: #e74c3c;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  margin-top: 16px;
}
.main-retry-btn:hover {
  background: #c0392b;
}
.processing-info {
  color: #f39c12;
  font-size: 12px;
  margin-left: 8px;
}
.pdf-container {
  width: 100%;
  max-width: 100%;
  overflow: hidden;
}
.preview-wrapper {
  width: 100%;
  max-width: 100%;
  overflow: hidden;
}
.preview-content {
  display: flex;
  width: 100%;
  max-width: 100%;
  gap: 20px;
}
.preview-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 16px;
}
.toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 8px 16px;
  background: #f9fafb;
  border-radius: 8px;
}
.toolbar-left,
.toolbar-right {
  display: flex;
  align-items: center;
  gap: 8px;
}
.canvas-container {
  flex: 1;
  display: flex;
  justify-content: center;
  align-items: center;
  background: #f3f4f6;
  border-radius: 8px;
  padding: 16px;
  height: 700px;
  overflow: hidden;
}
.image-wrapper {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100%;
  width: 100%;
  transition: transform 0.3s ease;
}
.pdf-image {
  max-height: 100%;
  max-width: 100%;
  object-fit: contain;
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
  border-radius: 4px;
}
.no-image-placeholder {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100%;
  width: 100%;
  background-color: #fafafa;
  border: 2px dashed #d1d5db;
  border-radius: 8px;
}
.placeholder-content {
  text-align: center;
  color: #6b7280;
}
.placeholder-icon {
  font-size: 48px;
  margin-bottom: 16px;
  display: block;
}
.loading-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(255, 255, 255, 0.8);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
}
.loading-spinner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}
.spinner {
  width: 50px;
  height: 50px;
  border: 5px solid #f3f3f3;
  border-top: 5px solid #3498db;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}
@keyframes spin {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}
.spinner-text {
  color: #3498db;
  font-size: 14px;
  text-align: center;
}
/* Responsive design */
@media (max-width: 768px) {
  .preview-content {
    flex-direction: column;
  }
  .thumbnail-sidebar {
    width: 100%;
    height: 120px;
    border-right: none;
    border-bottom: 1px solid #e5e7eb;
  }
  .thumbnail-list {
    flex-direction: row;
    overflow-x: auto;
    overflow-y: hidden;
  }
  .thumbnail-item {
    min-width: 80px;
    margin-right: 8px;
  }
  .canvas-container {
    height: 500px;
  }
  .toolbar {
    flex-wrap: wrap;
    gap: 8px;
  }
  .toolbar-left,
  .toolbar-right {
    flex-wrap: wrap;
  }
}
</style>
